Linux搜索命令find和grep使用总结 您所在的位置:网站首页 grep 使用变量 Linux搜索命令find和grep使用总结

Linux搜索命令find和grep使用总结

2023-12-03 03:15| 来源: 网络整理| 查看: 265

前言

find和grep是Linux最基本的搜索命令,find用于搜索文件,grep用于搜索文件内容,熟练掌握其用法可以显著提高搜索效率,本文总结了两者的

常规用法 配合正则表达式使用 两者结合使用 配合shell脚本自定义搜索函数 1. find 基本用法

搜索包含res的文件 find "res" 结果中不仅会包含/res文件夹,也会包含res/strings.xml等文件 参数 -name 搜索仅匹配文件名而非相对路径 例:在当前路径搜索名称为strings.xml的所有文件 find ./ –name strings.xml 参数 -not 非 例:在当前路径搜索除了strings.xml文件外的所有文件 find ./ -not -name "strings.xml" 参数 -a 与 例:在当前路径搜索除了strings.xml文件外的所有xml文件 find ./ -not -name "strings.xml" -a -name "*.xml" 参数 -o 或 例:在当前路径搜索所有的xml和java文件 find . -name "*.xml" -o -name "*.java" 参数 -type 指定搜索的文件类型 例:在当前路径搜索所有文件夹 find . -type d 例:在当前路径搜索所有普通文件 find . -type f

2. grep 基本用法

在文件内搜索文件内容 例:在当前路径下的MainActivity.java文件中搜索onCreate方法 grep "onCreate" ./MainActivity.java 参数 -n 输出的结果打印行号 参数 -r 递归搜索 例:在当前目录以及子目录中搜索onCreate方法 grep -nr "onCreate" 使用-r参数后不需要加文件名 参数 -i 搜索忽略大小写 参数 -I 搜索结果只显示文件名 参数 -w 精确匹配结果 参数 -v 输出所有不匹配的行

3. find + 正则表达式(RE) -name + RE 的使用

-name 是将文件名去匹配而不是文件的输出结果,以下为使用-name时的RE

符号 解释 * 代表任意字符(可以没有字符) ? 代表任意单个字符 [] 代表括号内的任意字符,[abc]可以匹配a\b\c某个字符 [a-z] 可以匹配a-z的某个字母 [A-Z] 可以匹配A-Z的某个字符 [0-9] 可以匹配0-9的某个数字 ^ 用在[]内的前缀表示不匹配[]中的字符 [^a-z] 表示不匹配a-z的某个字符

例1:在当前目录中搜素不以a、b、c开头的所有文件 find ./ –name “[^abc]*” 例2:在当前目录中搜索以大写字母或数字开头的所有文件 find ./ -name “[A-Z0-9]*”

 

-regex + RE 的使用

-regex 是将文件的输出结果进行匹配而不是文件名,使用-regex时必须使用正规的RE,以下为简单的RE使用

符号 解释 [] 代表括号内的任意字符,[abc]可以匹配a\b\c某个字符 [a-z] 可以匹配a-z的某个字母 [A-Z] 可以匹配A-Z的某个字符 [0-9] 可以匹配0-9的某个数字 . 表示任意单个字符 ? 表示前面的字符出现一次或零次 + 表示前面的字符至少出现一次 * 表示前面的字符出现零次或多次 () 将字符括起来后面跟量词 | 逻辑或,可以搜索两个条件

例1:搜索所有输出结果包含res的文件(即使文件名不包含res,只要该文件在res文件夹中也都可以被搜索到) find . –regex “.*res.*” 注意此时用的是.*而不是*去匹配任意字符 例:在当前目录搜索所有文件名末尾为res或res_ext的文件 find ./ -regex “.*res|.*res_ext”

4. grep + 正则表达式 (RE)

find中的RE使用均可使用,注意有些符号需要用\转义,其他常用符号如下

符号 解释 单词的结束 ^ 行的开始,^ 用在 [ ] 内表示不匹配其中的字符,注意区别 $ 行的结束 {n} 表示前面的字符匹配n次 {n,m} 表示前面的字符匹配n-m次 {,m} 表示前面的字符至多匹配的m次 {n,} 表示前面的字符至少匹配n次 egrep

egrep是grep的进化版,改进了许多grep中不方便之处如下,egrep使用RE符号 + , ? , | (或) , {} 时不用转义,如果要用其本身则需要转义,因此推荐使用egrep和RE配合使用

例1:搜索精确匹配Dialer单词的行(形如DialerActivity则不会匹配) egrep –nr “\” 例2:当前目录搜索以private开始的行(private前可能有空格) egrep -nr "^.*private"

5. find和grep结合使用

面对大量代码时仅使用grep搜索会非常耗时,此时就需要将find和grep结合起来使用以提高搜索效率,先看一个例子

function jgrep() { find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.java" -print0 | xargs -0 grep --color -n "$@" }

这个是Android系统源码build/envsetup.sh中的jgrep函数,用于搜索java文件内容,使用jgrep搜索效率远胜于单单使用grep进行搜索,下面对这个函数进行分析 find 在当前目录搜索 -o 或,并列多个条件 -name .repo –prune 忽略.repo目录(git库相关) -name .git –prune 忽略.git目录(git库相关) -name out –prune 忽略out目录(编译生成的目录) -type f 指定文件类型为普通文件 -name "*.java" 指定匹配的文件名为.java文件 -print0 | xargs -0 忽略搜索中可能出现的错误信息,并将搜索到的文件作为结果向后传递并继续执行 grep --color –n 用grep在之前搜索到的文件中进行内容搜索,输出行号并标识颜色 "$@" 表示在使用jgrep函数时输入的参数,这里即为egrep搜索的内容

管道符号以及xargs的使用

上例中的|为管道符号,作用是将前一个命令的标准输出作为后一个命令的标准输入。

如果仅使用|,那么前面的结果会作为输入直接传递到后面的命令中,而使用xargs,就可以使前面的结果作为参数传递到后面的命令中,而这个特性对于find和grep而言十分重要。

例1:在当前目录中搜索所有AndroidManifest.xml文件并在其中搜索DialtactsActivity

find . –name AndroidManifest.xml | xargs grep –n –color “DialtactsActivity”

该例是xargs最基本的用法,如果将xargs去掉,那么grep搜索的内容是find输出的结果内容而非结果文件中的内容

例2:在当前目录搜索所有的values-zh-rCN文件目录并在其中搜索所有的strings.xml文件,然后在搜索到的strings.xml文件中搜索“通话”字符串

find . –type d –name “values-zh-rCN” | xargs –i find {} –name “strings.xml” | xargs grep –n –-color 通话

该例中xargs后使用了-i参数,该参数的作用是可以将后面命令中的 {}符号视为前面find搜索的结果文件。本例中连续使用了两次xargs进行结果的传递

例3:在当前目录中的所有mk文件中搜索ro.build.type

find . –type f –name “*.mk” –print0 | xargs -0 grep –n –color “ro.build.type”

本例中和之前提到的jgrep函数都使用了–print0 | xargs -0进行结果传递而非单纯使用xargs,这样做的好处是如果find搜索会忽略可能出现的错误,使最终输出的结果更清晰,因此在使用xargs时建议按照–print0 | xargs -0方式书写命令

6. 编写搜索函数

find和grep的结合使用的命令较长,为方便起见,我们需要使用函数配合使用(形如上述的jgrep函数)。 下例中说明了如何编写搜索函数以及如何在Linux命令行中使用函数,这里可能需要用到简单的shell脚本命令:

编写简单的搜索函数

首先创建test.sh脚本文件并编写下述代码

function mkgrep() { find . -name .repo -prune -o -name .git -prune -o -name out -prune -o -type f -name "*\.mk" -print0 | xargs -0 grep --color -n "$@" }

函数的使用

#加载函数脚本,只需加载一次 source test.sh #在当前目录及子目录下的所有.mk文件中搜索Dialer mkgrep Dialer 编写复杂的搜索函数

首先创建test.sh脚本文件并编写下述代码

#文件内容搜索函数sep #参数1 必选 搜索内容 #参数2 可选 前缀-t 内容所在的文件类型(即文件后缀名,如java),缺省为所有文件类型 #参数3 可选 前缀-f 指定搜索的目录 缺省为当前目录及所有子目录 #用例 sep "ITelecomService.Stub" -t java aidl -f packages/ frameworks/ #用例解析 在packages、frameworks目录中的所有java、aidl文件中搜索"ITelecomService.Stub" function sep() { #文件内容=第一个参数 se_content=$1 #文件类型和搜索目录暂时=空 se_fileType="" se_folder="" #shift的作用是将第一个参数移除,即当前函数输入的第二个参数变成第一个参数,第三个变成第二个,以此类推 shift #判断当前第一个参数是否为-t,即文件类型是否指定,如果指定就取出文件类型放入se_fileType变量中 if [ "$1" = "-t" ];then #如果是-t就将这个参数移除 shift while ( [ "$1" != "-f" ] && [ -n "$1" ] ) do se_fileType="$se_fileType $1" shift done fi #判断当前第一个参数是否为-f,即搜索目录是否指定,如果指定就取出搜索目录放入se_folder变量中 if [ "$1" = "-f" ];then #如果是-f就将这个参数移除 shift while [ -n "$1" ] do se_folder="$se_folder $1" shift done fi #判断文件类型是否为空,不为空则建立循环分别搜索指定的文件类型 if [ -z $se_fileType ];then #这里如果搜索目录为空find会自动搜索当前目录及子目录,因此不用再做判断 #这里用到了egrep而不是grep,方便输入搜索内容时直接使用正则表达式 find $se_folder -type f -print0 | xargs -0 egrep -n --color "$se_content" else for ft in $se_fileType do find $se_folder -type f -name "*.$ft" -print0 | xargs -0 egrep -n --color "$se_content" done fi }

函数的使用

#加载函数脚本,只需加载一次 source sep.sh #在当前路径下的packages、frameworks目录中的所有.java和.aidl文件中搜索ITelecomService.Stub sep "ITelecomService.Stub" -t java aidl -f packages/ frameworks/


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有